﻿#region File and License Information
/*
<File>
	<License>
		Copyright © 2009 - 2017, Daniel Vaughan. All rights reserved.
		This file is part of Calcium (http://calciumsdk.net), 
		which is released under the MIT License.
		See file /Documentation/License.txt for details.
	</License>
	<CreationDate>2010-02-23 14:48:34Z</CreationDate>
</File>
*/
#endregion

using System;
using System.Windows;
using System.Windows.Controls;

namespace Outcoder.UI.Xaml
{
	/// <summary>
	/// Extension methods for the <see cref="ControlTemplate"/> class.
	/// </summary>
	public static class ControlTemplateExtensions
	{
		/// <summary>
		/// Finds the element in a template with the specified name.
		/// </summary>
		/// <typeparam name="T">The type of the element in the template.</typeparam>
		/// <param name="template">The template.</param>
		/// <param name="name">The name of the element to find.</param>
		/// <param name="templatedParent">The item having a template applied.</param>
		/// <returns>The element with the specified name.</returns>
		/// <exception cref="ArgumentNullException">Occurs if the specified name 
		/// or templateParent is <c>null</c></exception>
		/// <exception cref="InvalidCastException">
		/// Occurs if the located element is not of type T.</exception>
		public static T FindNamedElement<T>(this ControlTemplate template, 
			string name, FrameworkElement templatedParent) where T : class
		{
			ArgumentValidator.AssertNotNull(template, "template");
			ArgumentValidator.AssertNotNull(name, "name");
			ArgumentValidator.AssertNotNull(templatedParent, "owner");
			return (T)template.FindName(name, templatedParent);
		}

		/// <summary>
		/// Tries to find the element in a template with the specified name.
		/// </summary>
		/// <typeparam name="T">The type of the element in the template.</typeparam>
		/// <param name="template">The template.</param>
		/// <param name="name">The name of the element to find.</param>
		/// <param name="templatedParent">The item having a template applied.</param>
		/// <returns><c>true</c> if the element was found, <c>false</c> otherwise.</returns>
		/// <exception cref="ArgumentNullException">Occurs if the specified name 
		/// or templateParent is <c>null</c></exception>
		public static bool TryFindNamedElement<T>(this ControlTemplate template,
			string name, FrameworkElement templatedParent, out T element) where T : class
		{
			ArgumentValidator.AssertNotNull(template, "template");
			ArgumentValidator.AssertNotNull(name, "name");
			ArgumentValidator.AssertNotNull(templatedParent, "owner");
			element = template.FindName(name, templatedParent) as T;
			return element != null;
		}

		/// <summary>
		/// Finds the element in a template with the specified name.
		/// </summary>
		/// <typeparam name="T">The type of the element in the template.</typeparam>
		/// <param name="template">The template.</param>
		/// <param name="name">The name of the element to find.</param>
		/// <param name="templatedParent">The item having a template applied.</param>
		/// <returns>The element with the specified name.</returns>
		/// <exception cref="ArgumentNullException">Occurs if the specified name 
		/// or templateParent is <c>null</c></exception>
		/// <exception cref="TemplatePartMissingException">
		/// Occurs if a <seealso cref="FrameworkElement"/> with the specified name 
		/// is not found.</exception>
		/// <exception cref="InvalidCastException">
		/// Occurs if the located element is not of type T.</exception>
		public static T FindNamedElementAndAssertNotNull<T>(this ControlTemplate template, 
			string name, FrameworkElement templatedParent) where T : class
		{
			ArgumentValidator.AssertNotNull(template, "template");

			var result = template.FindNamedElement<T>(name, templatedParent);
			if (result == null)
			{
				throw new TemplatePartMissingException(name);
			}
			return result;
		}
	}
}
